﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using GameLib.Utils;

namespace GameLib.WorldMap
{
	public struct MapEdge
	{
		public GameVector TileA;
		public GameVector TileB;

		public MapEdge(GameVector tileA, GameVector tileB)
		{
			TileA = tileA;
			TileB = tileB;
		}

		public MapEdge(MapVertex vertA, MapVertex vertB)
		{
			if (!vertA.IsNeighbour(vertB))
			{
				TileA = new GameVector();
				TileB = new GameVector();
				return;
			}

			if (vertA.Location.Y == vertB.Location.Y)
			{
				int x = Math.Min(vertA.Location.X, vertB.Location.X);
				int y = vertA.Location.Y / 2;
				TileA =  new GameVector(x, y - 1);
				TileB =  new GameVector(x, y);
			}
			else
			{
				int x = vertA.Location.X;
				int y = Math.Min(vertA.Location.Y, vertB.Location.Y);

				if (x % 2 == 0)
				{
					TileA =  new GameVector(x - 1, (y + 1) / 2 - 1);
					TileB =  new GameVector(x, y / 2);
				}
				else
				{
					TileA =  new GameVector(x - 1, y / 2);
					TileB =  new GameVector(x, (y + 1) / 2 - 1);
				}
			}
		}

		public MapEdgeDirection Direction
		{
			get { return MapEdgeDirection.FromAToB(TileA, TileB); }
		}
	}

	public struct MapEdgeDirection : IEquatable<MapEdgeDirection>
	{
		public MapEdgeDirection(int index)
		{
			m_Index = index;
		}

		public int Index
		{
			get { return m_Index; }
		}

		public MapEdgeDirection Opposite
		{
			get
			{
				MapEdgeDirection dir = new MapEdgeDirection();
				dir.m_Index = (m_Index + MaxDirs / 2) % MaxDirs;
				return dir;
			}
		}

		public bool IsValid
		{
			get { return m_Index >= 0 && m_Index < MaxDirs; }
		}

		#region IEquatable<MapEdgeDirection> Members

		public bool Equals(MapEdgeDirection other)
		{
			return this.m_Index == other.m_Index;
		}

		public static MapEdgeDirection FromAToB(GameVector tileA, GameVector tileB)
		{
			int yDiff = tileB.Y - tileA.Y;
			if (tileA.X == tileB.X)
			{
				if (yDiff == -1)
					return North;
				else if (yDiff == 1)
					return South;
			}
			else
			{
				if (tileA.X % 2 == 0)
					yDiff += 1;

				if (tileA.X - 1 == tileB.X)
				{
					if (yDiff == 0)
						return NorthWest;
					else if (yDiff == 1)
						return SouthWest;
				}
				else if (tileA.X + 1 == tileB.X)
				{
					if (yDiff == 0)
						return NorthEast;
					else if (yDiff == 1)
						return SouthEast;
				}
			}

			return Invalid;
		}

		#endregion

		public static readonly MapEdgeDirection North = new MapEdgeDirection(0);
		public static readonly MapEdgeDirection NorthEast = new MapEdgeDirection(1);
		public static readonly MapEdgeDirection SouthEast = new MapEdgeDirection(2);
		public static readonly MapEdgeDirection South = new MapEdgeDirection(3);
		public static readonly MapEdgeDirection SouthWest = new MapEdgeDirection(4);
		public static readonly MapEdgeDirection NorthWest = new MapEdgeDirection(5);
		public static readonly int MaxDirs = 6;
		public static readonly MapEdgeDirection Invalid = new MapEdgeDirection(6);

		private int m_Index;
	}
}
